/*******************************************************************************
 * Copyright (c) 2011 Erik Byström.
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 ******************************************************************************/
package se.slackers.sounder;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.util.Arrays;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;

import se.slackers.sounder.algorithm.FloatGameOfLifeRule;
import se.slackers.sounder.ui.Field;

@SuppressWarnings("serial")
public class Sounder extends JFrame {
	private final SoundSystem system;
	private final Field field;

	public static void main(final String[] args) {
		final Sounder sounder = new Sounder();
		sounder.setVisible(true);
	}

	public Sounder() {
		super("Sounder");
		system = new SoundSystem(44100);
		field = new Field(24, 24, system, new FloatGameOfLifeRule());

		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		final JPanel panel = new JPanel(new BorderLayout(10, 10));
		final JPanel buttons = new JPanel(new FlowLayout(10));
		final JPanel scale = new JPanel(new FlowLayout(10));

		final JTextField interval = new JTextField("100", 5);
		interval.addFocusListener(new FocusListener() {
			public void focusLost(final FocusEvent arg0) {
				try {
					field.setInterval(Integer.parseInt(interval.getText()));
				} catch (final NumberFormatException e) {
					// :)
				}
			}

			public void focusGained(final FocusEvent arg0) {
			}
		});

		final JButton play = new JButton("Play");
		play.addActionListener(new ActionListener() {
			private boolean isplay = true;

			@Override
			public void actionPerformed(final ActionEvent e) {
				if (isplay) {
					play();
					play.setText("Pause");
				} else {
					pause();
					play.setText("Play");
				}
				isplay = !isplay;
			}
		});

		buttons.add(play);
		buttons.add(interval);
		buttons.add(createField(field, 0, 1f));
		buttons.add(createField(field, 1, 2.0f));
		buttons.add(createField(field, 2, 4.0f));
		buttons.add(createField(field, 3, 3.0f));
		buttons.add(createField(field, 4, 4.0f));

		final List<Integer> notes = Arrays.asList(0, 3, 5, 6, 7, 10);
		for (int i = 0; i < 12; i++) {
			scale.add(createField(system, i, notes.contains(i)));
		}

		final JPanel buttonPanel = new JPanel(new BorderLayout(5, 5));
		buttonPanel.add(buttons, BorderLayout.CENTER);
		buttonPanel.add(scale, BorderLayout.SOUTH);

		panel.add(field, BorderLayout.CENTER);
		panel.add(buttonPanel, BorderLayout.SOUTH);

		system.setRandomnessCallback(field);

		getContentPane().add(panel);
		setSize(field.getWidth() + 20, field.getHeight() + 75);
	}

	private static String[] names = new String[] { "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" };

	protected JCheckBox createField(final SoundSystem field, final int i, final boolean def) {
		field.setParam(i, def ? 1 : 0);
		final JCheckBox box = new JCheckBox();
		box.setText(names[i]);
		box.setSelected(def);
		box.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(final ActionEvent e) {
				field.setParam(i, box.isSelected() ? 1 : 0);
			}
		});
		return box;
	}

	protected JTextField createField(final Field field, final int i, final float defval) {
		final JTextField interval = new JTextField("1", 5);
		interval.addFocusListener(new FocusListener() {
			@Override
			public void focusLost(final FocusEvent arg0) {
				try {
					field.setParam(i, Float.parseFloat(interval.getText()));
				} catch (final NumberFormatException e) {
					// :)
				}
			}

			@Override
			public void focusGained(final FocusEvent arg0) {
			}
		});
		interval.setText(String.format("%.2f", defval));
		return interval;
	}

	protected void pause() {
		field.pause();
		system.pause();
	}

	protected void play() {
		field.play();
		system.play();
	}
}